home *** CD-ROM | disk | FTP | other *** search
/ Enter 2007 April / ENTER_CD_04_07.iso / Internet / WinHTTrack 3.23 / httrack-3.23.exe / {app} / src / htsname.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-03-08  |  44.5 KB  |  1,318 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       savename routine (compute output filename)             */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htsname.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htstools.h"
  43. #include "htsmd5.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <ctype.h>
  47. /* END specific definitions */
  48.  
  49. #undef test_flush
  50. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  51.  
  52. #define ADD_STANDARD_PATH \
  53.     {  /* ajout nom */\
  54.       char buff[HTS_URLMAXSIZE*2];\
  55.       buff[0]='\0';\
  56.       strncatbuff(buff,start_pos,(int) (nom_pos - start_pos));\
  57.       url_savename_addstr(save,buff);\
  58.     }
  59.  
  60. #define ADD_STANDARD_NAME(shortname) \
  61.     {  /* ajout nom */\
  62.       char buff[HTS_URLMAXSIZE*2];\
  63.       standard_name(buff,dot_pos,nom_pos,fil_complete,(shortname));\
  64.       url_savename_addstr(save,buff);\
  65.     }
  66.  
  67.  
  68. /* Avoid stupid DOS system folders/file such as 'nul' */
  69. /* Based on linux/fs/umsdos/mangle.c */
  70. static const char *hts_tbdev[] =
  71. {
  72.     "/prn", "/con", "/aux", "/nul",
  73.     "/lpt1", "/lpt2", "/lpt3", "/lpt4",
  74.     "/com1", "/com2", "/com3", "/com4",
  75.     "/clock$",
  76.     "/emmxxxx0", "/xmsxxxx0", "/setverxx",
  77.     ""
  78. };
  79.  
  80.  
  81.  
  82. // forme le nom du fichier α sauver (save) α partir de fil et adr
  83. // systΦme intelligent, qui renomme en cas de besoin (exemple: deux INDEX.HTML et index.html)
  84. int url_savename(char* adr_complete,char* fil_complete,char* save,char* former_adr,char* former_fil,char* referer_adr,char* referer_fil,httrackp* opt,lien_url** liens,int lien_tot,lien_back* back,int back_max,cache_back* cache,hash_struct* hash,int ptr,int numero_passe) {
  85.   char newfil[HTS_URLMAXSIZE*2];   /* ="" */
  86.   char* fil;
  87.   char* adr;
  88.   char* print_adr;
  89.   char *start_pos=NULL,*nom_pos=NULL,*dot_pos=NULL;  // Position nom et point
  90.   // pour changement d'extension ou de nom (content-disposition)
  91.   int ext_chg=0;
  92.   char ext[256];
  93.   int max_char=0;
  94.   //CLEAR
  95.   newfil[0]=ext[0]='\0';
  96.  
  97.   /* 8-3 ? */
  98.   switch(opt->savename_83) {
  99.   case 1:
  100.     max_char=8;
  101.     break;
  102.   case 2:
  103.     max_char=30;
  104.     break;
  105.   default:
  106.     max_char=8;
  107.     break;
  108.   }
  109.  
  110.   // effacer save
  111.   save[0]='\0';
  112.   // fil
  113.   fil = fil_complete;
  114.   // et adr (sauter user/pass)
  115.   // on prend le parti de mettre les fichiers avec login/pass au mΩme endroit que si ils
  116.   // Θtaient capturΘs sans ces paramΦtres
  117.   // c'est pour cette raison qu'on ignore totalement adr_complete (mΩme pour la recherche en table de hachage)
  118.   adr=jump_identification(adr_complete);
  119.  
  120.   // α afficher sans ftp://
  121.   print_adr=jump_protocol(adr);
  122.  
  123.   // court-circuit pour lien primaire
  124.   if (strnotempty(adr)==0) {
  125.     if (strcmp(fil,"primary")==0) {
  126.       strcatbuff(save,"primary.html");
  127.       return 0;
  128.     }
  129.   }
  130.  
  131.  
  132.   // vΘrifier que le nom n'a pas dΘja ΘtΘ calculΘ (si oui le renvoyer tel que)
  133.   // vΘrifier que le nom n'est pas dΘja pris...
  134.   // NOTE: si on cherche /toto/ et que /toto est trouvΘ on le prend (et rΘciproquqment) ** // **
  135.   if (liens!=NULL) { 
  136.     int i;
  137.  
  138. #if HTS_HASH
  139.     i=hash_read(hash,adr,fil_complete,1);      // recherche table 1 (adr+fil)
  140.     if (i>=0) {    // ok, trouvΘ
  141.       strcpybuff(save,liens[i]->sav);
  142.       return 0;
  143.     }
  144.     i=hash_read(hash,adr,fil_complete,2);      // recherche table 2 (former_adr+former_fil)
  145.     if (i>=0) {    // ok, trouvΘ
  146.       // copier location moved!
  147.       strcpybuff(adr_complete,liens[i]->adr);
  148.       strcpybuff(fil_complete,liens[i]->fil);
  149.       // et save
  150.       strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  151.       return 0;
  152.     }
  153. #else
  154.     for(i=lien_tot-1;i>=0;i--) {        
  155. #if HTS_CASSE
  156.       if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  157. #else
  158.       if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  159. #endif
  160.       {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  161.         strcpybuff(save,liens[i]->sav);
  162.         return 0;
  163.       }
  164.       if (liens[i]->former_adr) {     // tester ancienne loc?
  165. #if HTS_CASSE
  166.         if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete)==0))
  167. #else
  168.         if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete)))
  169. #endif
  170.         {
  171.           // copier location moved!
  172.           strcpybuff(adr_complete,liens[i]->adr);
  173.           strcpybuff(fil_complete,liens[i]->fil);
  174.           // et save
  175.           strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  176.           return 0;
  177.         }
  178.       }
  179.     }
  180. #endif
  181.  
  182.     // chercher sans / ou avec / dans former
  183.     {
  184.       char fil_complete_patche[HTS_URLMAXSIZE*2];
  185.       strcpybuff(fil_complete_patche,fil_complete);
  186.       // Version avec ou sans /
  187.       if (fil_complete_patche[strlen(fil_complete_patche)-1]=='/')
  188.         fil_complete_patche[strlen(fil_complete_patche)-1]='\0';
  189.       else
  190.         strcatbuff(fil_complete_patche,"/");
  191. #if HTS_HASH
  192.       i=hash_read(hash,adr,fil_complete_patche,2);      // recherche table 2 (former_adr+former_fil)
  193.       if (i>=0) {
  194.         // Θcraser fil et adr (pas former_fil?????)
  195.         strcpybuff(adr_complete,liens[i]->adr);
  196.         strcpybuff(fil_complete,liens[i]->fil);
  197.         // Θcrire save
  198.         strcpybuff(save,liens[i]->sav);
  199.         return 0;
  200.       }
  201. #else
  202.       // mΩme boucle en gros
  203.       for(i=lien_tot-1;i>=0;i--) {        
  204.         if (liens[i]->former_adr) {    // former-adr?
  205. #if HTS_CASSE
  206.           if ((strcmp(liens[i]->former_adr,adr)==0) && (strcmp(liens[i]->former_fil,fil_complete_patche)==0))
  207. #else
  208.           if ((strfield2(liens[i]->former_adr,adr)) && (strfield2(liens[i]->former_fil,fil_complete_patche)))
  209. #endif
  210.           {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  211.             // Θcraser fil et adr (pas former_fil?????)
  212.             strcpybuff(adr_complete,liens[i]->adr);
  213.             strcpybuff(fil_complete,liens[i]->fil);
  214.             // Θcrire save
  215.             strcpybuff(save,liens[i]->sav);
  216.             return 0;
  217.           }
  218.         }
  219.       }
  220. #endif
  221.     }
  222.   }
  223.  
  224.   // vΘrifier la non prΘsence de paramΦtres dans le nom de fichier
  225.   // si il y en a, les supprimer (ex: truc.cgi?subj=aspirateur)
  226.   // nΘanmoins, gardΘ pour vΘrifier la non duplication (voir aprΦs)
  227.   {
  228.     char* a;
  229.     a=strchr(fil,'?');
  230.     if (a!=NULL) {
  231.       strncatbuff(newfil,fil,(int) (a - fil));
  232.     } else {
  233.       strcpybuff(newfil,fil);
  234.     }
  235.     fil=newfil;
  236.   }
  237.   // dΘcoder %
  238.   strcpybuff(fil,unescape_http(fil));
  239.   /*
  240.   {
  241.     char tempo[HTS_URLMAXSIZE*2];
  242.     int i,j=0;
  243.     for (i=0;i<(int) strlen(fil);i++) {
  244.       if (fil[i]=='%') {
  245.         i++;
  246.         tempo[j++]=(char) ehex(fil+i);
  247.         i++;    // sauter 2 caractΦres finalement
  248.       } else
  249.         tempo[j++]=fil[i];
  250.     }
  251.     tempo[j++]='\0';
  252.     strcpybuff(fil,tempo);
  253.   }
  254.   */
  255.   
  256.   
  257.   /* replace shtml to html.. */
  258.   switch (ishtml(fil)) {       /* .html,.shtml,.. */
  259.   case 1:
  260.     if ( 
  261.       (strcmp(get_ext(fil),"html") != 0)
  262.       && (strcmp(get_ext(fil),"htm") != 0)
  263.       ) {
  264.       strcpybuff(ext,"html");
  265.       ext_chg=1;
  266.     }
  267.     break;
  268.     case 0:
  269.       if (!strnotempty(ext)) {
  270.         if (is_userknowntype(get_ext(fil))) {      // mime known by user
  271.           char mime[1024];
  272.           mime[0]=ext[0]='\0';
  273.           get_userhttptype(0,mime,get_ext(fil));
  274.           if (strnotempty(mime)) {
  275.             give_mimext(ext,mime);
  276.             if (strnotempty(ext)) {
  277.               ext_chg=1;
  278.             }
  279.           }
  280.         }
  281.       }
  282.       break;
  283.   }
  284.   
  285.  
  286.   // si option check_type activΘe
  287.   if ((opt->check_type) && (!ext_chg)) {
  288.     int ishtest;
  289.     if ( (!strfield(adr_complete,"file://")) 
  290.       && (!strfield(adr_complete,"ftp://")) 
  291.       ) {
  292.       // tester type avec requΦte HEAD si on ne connait pas le type du fichier
  293.       if (!(   (opt->check_type==1) && (fil[strlen(fil)-1]=='/')   ))    // slash doit Ωtre html?
  294.       if ((ishtest=ishtml(fil)) < 0) { // on ne sait pas si c'est un html ou un fichier..
  295.         // lire dans le cache
  296.         htsblk r = cache_read(opt,cache,adr,fil,NULL,NULL);              // test uniquement
  297.         if (r.statuscode != -1) {  // pas d'erreur de lecture cache
  298.           char s[16]; s[0]='\0';
  299.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  300.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type (from cache) %s%s"LF,adr_complete,fil_complete);
  301.             test_flush;
  302.           }
  303.           if (strnotempty(r.cdispo)) {        /* filename given */
  304.             ext_chg=2;      /* change filename */
  305.             strcpybuff(ext,r.cdispo);
  306.           }
  307.           else if (!may_unknown(r.contenttype) || ishtest == -2) {  // on peut patcher α priori?
  308.             give_mimext(s,r.contenttype);  // obtenir extension
  309.             if (strnotempty(s)>0) {        // on a reconnu l'extension
  310.               ext_chg=1;
  311.               strcpybuff(ext,s);
  312.             }
  313.           }
  314.           //
  315.         } else {          // test imposible dans le cache, faire une requΩte
  316.           //
  317. #if HTS_ANALYSTE
  318.           int hihp=_hts_in_html_parsing;
  319. #endif
  320.           int has_been_moved=0;
  321.           char curr_adr[HTS_URLMAXSIZE*2],curr_fil[HTS_URLMAXSIZE*2];
  322.           curr_adr[0]=curr_fil[0]='\0';
  323. #if HTS_ANALYSTE
  324.           _hts_in_html_parsing=2;  // test
  325. #endif
  326.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  327.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type %s%s"LF,adr_complete,fil_complete);
  328.             test_flush;
  329.           }
  330.           strcpybuff(curr_adr,adr_complete);
  331.           strcpybuff(curr_fil,fil_complete);
  332.           // ajouter dans le backing le fichier en mode test
  333.           // savename: rien car en mode test
  334.           if (back_add(back,back_max,opt,cache,curr_adr,curr_fil,BACK_ADD_TEST,referer_adr,referer_fil,1,NULL)!=-1) {
  335.             int b;
  336.             b=back_index(back,back_max,curr_adr,curr_fil,BACK_ADD_TEST);         
  337.             if (b>=0) {
  338.               int stop_looping=0;
  339.               int petits_tours=0;
  340.               int get_test_request=0;       // en cas de bouclage sur soi mΩme avec HEAD, tester avec GET.. parfois c'est la cause des problΦmes
  341.               do {
  342.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  343.                 if (back[b].status>0) back_wait(back,back_max,opt,cache,0);        
  344.                 if (ptr>=0)
  345.                   back_fillmax(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  346.   
  347.                 // on est obligΘ d'appeler le shell pour le refresh..
  348. #if HTS_ANALYSTE
  349.                 {
  350.                   
  351.                   // Transfer rate
  352.                   engine_stats();
  353.                   
  354.                   // Refresh various stats
  355.                   HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  356.                   HTS_STAT.stat_errors=fspc(NULL,"error");
  357.                   HTS_STAT.stat_warnings=fspc(NULL,"warning");
  358.                   HTS_STAT.stat_infos=fspc(NULL,"info");
  359.                   HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  360.                   HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  361.  
  362.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  363.                     return -1;
  364.                   } else if (_hts_cancel) {    // cancel 2 ou 1 (cancel parsing)
  365.                     back_delete(back,b);       // cancel test
  366.                     stop_looping = 1;
  367.                   }
  368.                 }
  369. #endif
  370.                 
  371.                 
  372.                 // traitement des 304,303..
  373.                 if (back[b].status<=0) {
  374.                   if (    (back[b].r.statuscode==301)
  375.                        || (back[b].r.statuscode==302)
  376.                        || (back[b].r.statuscode==303)
  377.                        || (back[b].r.statuscode==307)
  378.                      ) {    // agh moved.. un tit tour de plus
  379.                     if ((petits_tours<5) && (former_adr) && (former_fil)) { // on va pas tourner en rond non plus!
  380.                       if ((int) strnotempty(back[b].r.location)) {    // location existe!
  381.                         char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  382.                         mov_url[0]=mov_adr[0]=mov_fil[0]='\0';
  383.                         //
  384.                         strcpybuff(mov_url,back[b].r.location);    // copier URL
  385.                         if (ident_url_relatif(mov_url,curr_adr,curr_fil,mov_adr,mov_fil)>=0) {                        
  386.                           // si non bouclage sur soi mΩme, ou si test avec GET non testΘ
  387.                           if ((strcmp(mov_adr,curr_adr)) || (strcmp(mov_fil,curr_fil)) || (get_test_request==0)) {
  388.                             // bouclage?
  389.                             if ((!strcmp(mov_adr,curr_adr)) && (!strcmp(mov_fil,curr_fil)))
  390.                               get_test_request=1;     // faire requΦte avec GET
  391.  
  392.                             // recopier former_adr/fil?
  393.                             if ((former_adr) && (former_fil)) {
  394.                               if (strnotempty(former_adr)==0) {    // Pas dΘja notΘ
  395.                                 strcpybuff(former_adr,curr_adr);
  396.                                 strcpybuff(former_fil,curr_fil);
  397.                               }
  398.                             }
  399.  
  400.                             // check explicit forbidden - don't follow 3xx in this case
  401.                             {
  402.                               int set_prio_to=0;
  403.                               robots_wizard* robots = (robots_wizard*) opt->robotsptr;
  404.                               if (hts_acceptlink(opt,ptr,lien_tot,liens,
  405.                                 mov_adr,mov_fil,
  406.                                 opt->filters.filters,opt->filters.filptr,opt->maxfilter,
  407.                                 robots,
  408.                                 &set_prio_to,
  409.                                 NULL) == 1) 
  410.                               {  /* forbidden */
  411.                                 has_been_moved = 1;
  412.                                 back_maydelete(back,opt,b);    // ok
  413.                                 strcpybuff(curr_adr,mov_adr);
  414.                                 strcpybuff(curr_fil,mov_fil);
  415.                                 mov_url[0]='\0';
  416.                                 stop_looping = 1;
  417.                               }
  418.                             }
  419.                             
  420.                             // ftp: stop!
  421.                             if (strfield(mov_url,"ftp://")) {    // ftp, ok on arrΩte
  422.                               has_been_moved = 1;
  423.                               back_maydelete(back,opt,b);    // ok
  424.                               strcpybuff(curr_adr,mov_adr);
  425.                               strcpybuff(curr_fil,mov_fil);
  426.                               stop_looping = 1;
  427.                             } else if (*mov_url) {
  428.                               char* methode;
  429.                               if (!get_test_request)
  430.                                 methode=BACK_ADD_TEST;      // tester avec HEAD
  431.                               else {
  432.                                 methode=BACK_ADD_TEST2;     // tester avec GET
  433.                                 if ( opt->errlog!=NULL ) {
  434.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Loop with HEAD request (during prefetch) at %s%s"LF,curr_adr,curr_fil);
  435.                                   test_flush;
  436.                                 }                    
  437.                               }
  438.                               // Ajouter
  439.                               if (back_add(back,back_max,opt,cache,mov_adr,mov_fil,methode,referer_adr,referer_fil,1,NULL)!=-1) {    // OK
  440.                                 if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  441.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"(during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  442.                                   test_flush;
  443.                                 }
  444.                                 
  445.                                 // libΘrer emplacement backing actuel et attendre le prochain
  446.                                 back_maydelete(back,opt,b);
  447.                                 strcpybuff(curr_adr,mov_adr);
  448.                                 strcpybuff(curr_fil,mov_fil);
  449.                                 b=back_index(back,back_max,curr_adr,curr_fil,methode);         
  450.                                 if (!get_test_request)
  451.                                   has_been_moved = 1;       // sinon ne pas forcer has_been_moved car non dΘplacΘ
  452.                                 petits_tours++;
  453.                                 //
  454.                               } else {// sinon on fait rien et on s'en va.. (ftp etc)
  455.                                 if ( (opt->debug>1)  && (opt->errlog)) {
  456.                                   fspc(opt->errlog,"debug"); fprintf(opt->errlog,"Warning: Savename redirect backing error at %s%s"LF,mov_adr,mov_fil);
  457.                                   test_flush;
  458.                                 } 
  459.                               }
  460.                             }
  461.                           } else {
  462.                             if ( opt->errlog!=NULL ) {
  463.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop to same filename)"LF,adr_complete,fil_complete);
  464.                               test_flush;
  465.                             }
  466.                           }
  467.                           
  468.                         }
  469.                       }
  470.                     } else{  // arrΩter les frais
  471.                       if ( opt->errlog!=NULL ) {
  472.                         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop)"LF,adr_complete,fil_complete);
  473.                         test_flush;
  474.                       }
  475.                     }
  476.                   }  // ok, leaving
  477.                 }
  478.               } while(!stop_looping && back[b].status > 0 && back[b].status < 1000);
  479.               
  480.               // Si non dΘplacΘ, forcer type?
  481.               if (!has_been_moved) {
  482.                 if (back[b].r.statuscode!=-10) {    // erreur
  483.                   if (strnotempty(back[b].r.contenttype)==0)
  484.                     strcpybuff(back[b].r.contenttype,"text/html");    // message d'erreur en html
  485.                   // Finalement on, renvoie un erreur, pour ne toucher α rien dans le code
  486.                   // libΘrer emplacement backing
  487.                   /*if (opt->errlog!=NULL) {
  488.                     fspc(opt->errlog,0); fprintf(opt->errlog,"Error: (during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  489.                     test_flush;
  490.                   }                    
  491.                   back_delete(back,b);
  492.                   return -1;        // ERREUR (404 par exemple)
  493.                   */
  494.                 } 
  495.                 
  496.                 {            // pas d'erreur, changer type?
  497.                   char s[16];
  498.                   s[0]='\0';
  499.                   if (strnotempty(back[b].r.cdispo)) {        /* filename given */
  500.                     ext_chg=2;      /* change filename */
  501.                     strcpybuff(ext,back[b].r.cdispo);
  502.                   }
  503.                   else if (!may_unknown(back[b].r.contenttype) || ishtest == -2 ) {  // on peut patcher α priori? (pas interdit ou pas de type)
  504.                     give_mimext(s,back[b].r.contenttype);  // obtenir extension
  505.                     if (strnotempty(s)>0) {    // on a reconnu l'extension
  506.                       ext_chg=1;
  507.                       strcpybuff(ext,s);
  508.                     }
  509.                   }
  510.                 }
  511.               }
  512.               // FIN Si non dΘplacΘ, forcer type?
  513.  
  514.               // libΘrer emplacement backing
  515.               back_maydelete(back,opt,b);
  516.               
  517.               // --- --- ---
  518.               // oops, a ΘtΘ dΘplacΘ.. on recalcule en rΘcursif (osons!)
  519.               if (has_been_moved) {
  520.                 // copier adr, fil (optionnel, mais sinon marche pas pour le rip)
  521.                 strcpybuff(adr_complete,curr_adr);
  522.                 strcpybuff(fil_complete,curr_fil);
  523.                 // copier adr, fil
  524.                 
  525.                 return url_savename(curr_adr,curr_fil,save,NULL,NULL,referer_adr,referer_fil,opt,liens,lien_tot,back,back_max,cache,hash,ptr,numero_passe);
  526.               }
  527.               // --- --- ---
  528.               
  529.             }
  530.             
  531.           } else {
  532.             printf("PANIC! : Savename Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  533. #if BDEBUG==1
  534.             printf("error while savename crash adding\n");
  535. #endif
  536.             if (opt->errlog) {
  537.               fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unexpected savename backing error at %s%s"LF,adr,fil_complete);
  538.               test_flush;
  539.             } 
  540.             
  541.           }
  542.           // restaurer
  543. #if HTS_ANALYSTE
  544.           _hts_in_html_parsing=hihp;
  545. #endif
  546.         }  // cachΘ?
  547.       }
  548.     }
  549.   }
  550.  
  551.  
  552.  
  553.   // - - - DEBUT NOMMAGE - - -
  554.  
  555.   // Donner nom par dΘfaut?
  556.   if (fil[strlen(fil)-1]=='/')  {
  557.     if (!strfield(adr_complete,"ftp://"))
  558.       strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut!!
  559.     else {
  560.       if (!opt->proxy.active)
  561.         strcatbuff(fil,DEFAULT_FTP);     // nommer page par dΘfaut (texte)
  562.       else
  563.         strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut (α priori ici html depuis un proxy http)
  564.     }
  565.   }
  566.   // Changer extension?
  567.   // par exemple, php3 sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  568.   if (ext_chg) {  // changer ext
  569.     char* a=fil+strlen(fil)-1;
  570.     if ( (opt->debug>1) && (opt->log!=NULL) ) {
  571.       fspc(opt->log,"debug");
  572.       if (ext_chg==1)
  573.         fprintf(opt->log,"Changing link extension %s%s to .%s"LF,adr_complete,fil_complete,ext);
  574.       else
  575.         fprintf(opt->log,"Changing link name %s%s to %s"LF,adr_complete,fil_complete,ext);
  576.       test_flush;
  577.     }
  578.     if (ext_chg==1) {
  579.       while((a > fil) && (*a!='.') && (*a!='/')) a--;
  580.       if (*a=='.') *a='\0';  // couper
  581.       strcatbuff(fil,".");      // recopier point
  582.     } else {
  583.       while(( a > fil) && (*a!='/')) a--;
  584.       if (*a=='/') a++;
  585.       *a='\0';
  586.    }
  587.     strcatbuff(fil,ext);    // copier ext/nom
  588.   }
  589.  
  590.   // Rechercher premier / et dernier .
  591.   {  
  592.     char* a=fil+strlen(fil)-1;
  593.  
  594.     // passer structures
  595.     start_pos=fil;
  596.     while(( a > fil) && (*a != '/') && (*a != '\\')) {
  597.       if (*a == '.')    // point? noter position
  598.         if (!dot_pos)
  599.           dot_pos=a;
  600.         a--;
  601.     }
  602.     if ((*a=='/') || (*a=='\\')) a++;
  603.     nom_pos = a;
  604.   }
  605.  
  606.   
  607.   // un nom de fichier est gΘnΘrΘ
  608.   // s'il existe dΘja, alors on le mofifie lΘgΦrement
  609.  
  610.   // ajouter nom du site Θventuellement en premier
  611.   if (opt->savename_type == -1) {    // utiliser savename_userdef! (%h%p/%n%q.%t)
  612.     char* a = opt->savename_userdef;
  613.     char* b = save;
  614.     /*char *nom_pos=NULL,*dot_pos=NULL;  // Position nom et point */
  615.     char tok;
  616.  
  617.     /*
  618.     {  // Rechercher premier /
  619.       char* a=fil+strlen(fil)-1;
  620.       // passer structures
  621.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  622.         if (*a == '.')    // point? noter position
  623.         if (!dot_pos)
  624.           dot_pos=a;
  625.         a--;
  626.       }
  627.       if ((*a=='/') || (*a=='\\')) a++;
  628.       nom_pos = a;
  629.     }
  630.     */
  631.  
  632.     // Construire nom
  633.     while ((*a) && (((int) (b - save)) < HTS_URLMAXSIZE ) ) {    // parser, et pas trop long..
  634.       if (*a == '%') {
  635.         int short_ver=0;
  636.         a++;
  637.         if (*a == 's') {
  638.           short_ver=1;
  639.           a++;
  640.         }
  641.         *b='\0';
  642.         switch(tok=*a++) {
  643.           case '[':            // %[param:prefix_if_not_empty:suffix_if_not_empty:empty_replacement:notfound_replacement]
  644.             if (strchr(a,']')) {
  645.               int pos=0;
  646.               char name[5][256];
  647.               char* c=name[0];
  648.               for(pos = 0 ; pos < 5 ; pos++) {
  649.                 name[pos][0]='\0';
  650.               }
  651.               pos=0;
  652.               while(*a!=']') {
  653.                 if (pos < 5) {
  654.                   if (*a == ':') {  // next token
  655.                     c=name[++pos];
  656.                     a++;
  657.                   } else {
  658.                     *c++=*a++;
  659.                     *c='\0';
  660.                   }
  661.                 }
  662.               }
  663.               a++;
  664.               strcatbuff(name[0],"=");           /* param=.. */
  665.               c=strchr(fil_complete,'?');
  666.               /* parameters exists */
  667.               if (c) {
  668.                 char* cp;
  669.                 while((cp = strstr(c+1, name[0])) && *(cp-1) != '?' && *(cp-1) != '&') {     /* finds [?&]param= */
  670.                   c = cp;
  671.                 }
  672.                 if (cp) {
  673.                   c = cp + strlen(name[0]);    /* jumps "param=" */
  674.                   strcpybuff(b, name[1]);    /* prefix */
  675.                   b += strlen(b);
  676.                   if (*c != '\0' && *c != '&') {
  677.                     char* d = name[0];
  678.                     /* */
  679.                     while(*c != '\0' && *c != '&') {
  680.                       *d++ = *c++;
  681.                     }
  682.                     *d = '\0';
  683.                     d = unescape_http(name[0]);
  684.                     if (d && *d) {
  685.                       strcpybuff(b, d);         /* value */
  686.                       b += strlen(b);
  687.                     } else {
  688.                       strcpybuff(b, name[3]);    /* empty replacement if any */
  689.                       b += strlen(b);
  690.                     }
  691.                   } else {
  692.                     strcpybuff(b, name[3]);    /* empty replacement if any */
  693.                     b += strlen(b);
  694.                   }
  695.                   strcpybuff(b, name[2]);    /* suffix */
  696.                   b += strlen(b);
  697.                 } else {
  698.                   strcpybuff(b, name[4]);    /* not found replacement if any */
  699.                   b += strlen(b);
  700.                 }
  701.               }
  702.             }
  703.           break;
  704.           case '%': *b++='%'; break;
  705.           case 'n':    // nom sans ext
  706.             if (dot_pos) {
  707.               if (!short_ver)    // Noms longs
  708.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  709.               else
  710.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  711.             } else {
  712.               if (!short_ver)    // Noms longs
  713.                 strcpybuff(b,nom_pos);
  714.               else
  715.                 strncatbuff(b,nom_pos,8);
  716.             }
  717.             b+=strlen(b);   // pointer α la fin
  718.             break;
  719.           case 'N':    // nom avec ext
  720.             // RECOPIE NOM + EXT
  721.             *b='\0';
  722.             if (dot_pos) {
  723.               if (!short_ver)    // Noms longs
  724.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  725.               else
  726.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  727.             } else {
  728.               if (!short_ver)    // Noms longs
  729.                 strcpybuff(b,nom_pos);
  730.               else
  731.                 strncatbuff(b,nom_pos,8);
  732.             }
  733.             b+=strlen(b);   // pointer α la fin
  734.             // RECOPIE NOM + EXT
  735.             *b='\0';
  736.             if (dot_pos) {
  737.               if (!short_ver)    // Noms longs
  738.                 strcpybuff(b,dot_pos+1);
  739.               else
  740.                 strncatbuff(b,dot_pos+1,3);
  741.             } else {
  742.               if (!short_ver)    // Noms longs
  743.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  744.               else
  745.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  746.             }
  747.             b+=strlen(b);   // pointer α la fin
  748.             //
  749.             break;
  750.           case 't':    // ext
  751.             *b='\0';
  752.             if (dot_pos) {
  753.               if (!short_ver)    // Noms longs
  754.                 strcpybuff(b,dot_pos+1);
  755.               else
  756.                 strncatbuff(b,dot_pos+1,3);
  757.             } else {
  758.               if (!short_ver)    // Noms longs
  759.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  760.               else
  761.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  762.             }
  763.             b+=strlen(b);   // pointer α la fin
  764.             break;
  765.           case 'p':    // path sans dernier /
  766.             *b='\0';
  767.             if (nom_pos != fil + 1) { // pas: /index.html (chemin nul)
  768.               if (!short_ver) {   // Noms longs
  769.                 strncatbuff(b,fil,(int) (nom_pos - fil) - 1);
  770.               } else {
  771.                 char pth[HTS_URLMAXSIZE*2],n83[HTS_URLMAXSIZE*2];
  772.                 pth[0]=n83[0]='\0';
  773.                 //
  774.                 strncatbuff(pth,fil,(int) (nom_pos - fil) - 1);
  775.                 long_to_83(opt->savename_83,n83,pth);
  776.                 strcpybuff(b,n83);
  777.               }
  778.             }
  779.             b+=strlen(b);   // pointer α la fin
  780.             break;
  781.           case 'h':    // host
  782.             *b='\0';
  783.             if (strcmp(adr_complete,"file://")==0) {
  784.               if (!short_ver)    // Noms longs
  785.                 strcpybuff(b,"localhost");
  786.               else
  787.                 strcpybuff(b,"local");
  788.             } else {
  789.               if (!short_ver)    // Noms longs
  790.                 strcpybuff(b,print_adr);
  791.               else
  792.                 strncatbuff(b,print_adr,8);
  793.             }
  794.             b+=strlen(b);   // pointer α la fin
  795.             break;
  796.           case 'M':         /* host/address?query MD5 (128-bits) */
  797.             *b='\0';
  798.             {
  799.               char digest[32+2];
  800.               char buff[HTS_URLMAXSIZE*2];
  801.               digest[0]=buff[0]='\0';
  802.               strcpybuff(buff,adr);
  803.               strcatbuff(buff,fil_complete);
  804.               domd5mem(buff,strlen(buff),digest,1);
  805.               strcpybuff(b,digest);
  806.             }
  807.             b+=strlen(b);   // pointer α la fin
  808.             break;
  809.           case 'Q': case 'q':         /* query MD5 (128-bits/16-bits) 
  810.                                          GENERATED ONLY IF query string exists! */
  811.             *b='\0';
  812.             strncatbuff(b,url_md5(fil_complete),(tok == 'Q')?32:4);
  813.             b+=strlen(b);   // pointer α la fin
  814.             break;
  815.         }
  816.       } else
  817.         *b++=*a++;
  818.     }
  819.     *b++='\0';
  820.     //
  821.     // Types prΘdΘfinis
  822.     //
  823.  
  824.   } 
  825.   //
  826.   // Structure originale
  827.   else if (opt->savename_type%100==0) { 
  828.     /* recopier www.. */
  829.     if (opt->savename_type!=100) {  
  830.       if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  831.         if (strcmp(adr_complete,"file://")==0) {
  832.           //## if (*adr==lOCAL_CHAR) {
  833.           if (opt->savename_83 != 1)  // noms longs
  834.             strcatbuff(save,"localhost");
  835.           else
  836.             strcatbuff(save,"local");
  837.         } else {
  838.           // adresse url
  839.           if (!opt->savename_83) {  // noms longs (et pas de .)
  840.             strcatbuff(save,print_adr);
  841.           } else {  // noms 8-3
  842.             if (strlen(print_adr)>4) {
  843.               if (strfield(print_adr,"www."))
  844.                 strncatbuff(save,print_adr+4,max_char);
  845.               else
  846.                 strncatbuff(save,print_adr,8);
  847.             } else strncatbuff(save,print_adr,max_char);
  848.           }
  849.         }
  850.         if (*fil!='/') strcatbuff(save,"/");
  851.       }
  852.     }
  853.   
  854. #if HTS_CASSE==0
  855.     hts_lowcase(save);
  856. #endif  
  857.         
  858.     /*
  859.     // ne sert α rien car a dΘja ΘtΘ filtrΘ normalement
  860.     if ((*fil=='.') && (*(fil+1)=='/'))          // ./index.html ** //
  861.       url_savename_addstr(save,fil+2);
  862.     else                                               // index.html ou /index.html
  863.       url_savename_addstr(save,fil);
  864.     if (save[strlen(save)-1]=='/') 
  865.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  866. */
  867.  
  868.     /* add name */
  869.     ADD_STANDARD_PATH;
  870.     ADD_STANDARD_NAME(0);
  871.  
  872.   }
  873.   //
  874.   // Structure html/image
  875.   else {    
  876.     // dossier "web" ou "www.xxx" ?
  877.     if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  878.       if ((opt->savename_type/100)%2) {
  879.         if (strcmp(adr_complete,"file://")==0) {
  880.         //## if (*adr==lOCAL_CHAR) {
  881.           if (opt->savename_83 != 1)  // noms longs
  882.             strcatbuff(save,"localhost/");
  883.           else
  884.             strcatbuff(save,"local/");
  885.         } else {
  886.           // adresse url
  887.           if (!opt->savename_83) {  // noms longs
  888.             strcatbuff(save,print_adr); strcatbuff(save,"/");
  889.           } else {  // noms 8-3
  890.             if (strlen(print_adr)>4) {
  891.               if (strfield(print_adr,"www."))
  892.                 strncatbuff(save,print_adr+4,max_char);
  893.               else
  894.                 strncatbuff(save,print_adr,max_char);
  895.               strcatbuff(save,"/");
  896.             } else { 
  897.               strncatbuff(save,print_adr,max_char); strcatbuff(save,"/");
  898.             }
  899.           }
  900.         }
  901.       } else {
  902.         strcatbuff(save,"web/");    // rΘpertoire gΘnΘral
  903.       }
  904.     } 
  905.  
  906.     // si un html α coup s√r
  907.     if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  908.       if (opt->savename_type%100==2) {  // html/
  909.         strcatbuff(save,"html/");
  910.       }
  911.     } else {
  912.       if ((opt->savename_type%100==1) || (opt->savename_type%100==2)) {  // html & images
  913.         strcatbuff(save,"images/");
  914.       }
  915.     }
  916.     
  917.     switch (opt->savename_type%100) {
  918.     case 4: case 5: {           // sΘparer par types
  919.       char* a=fil+strlen(fil)-1;
  920.       // passer structures
  921.       while(( a > fil) && (*a != '/') && (*a != '\\')) a--;      
  922.       if ((*a=='/') || (*a=='\\')) a++;
  923.  
  924.       // html?
  925.       if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  926.         if (opt->savename_type%100==5)
  927.           strcatbuff(save,"html/");
  928.       } else {
  929.         char* a=fil+strlen(fil)-1;
  930.         while(( a> fil) && (*a != '/') && (*a != '.')) a--;      
  931.         if (*a!='.')
  932.           strcatbuff(save,"other");
  933.         else
  934.           strcatbuff(save,a+1);
  935.         strcatbuff(save,"/");
  936.       }
  937.       /*strcatbuff(save,a);*/
  938.       /* add name */
  939.       ADD_STANDARD_NAME(0);
  940.             }
  941.       break;
  942.     case 99: {                  // 'codΘ' .. c'est un gadget
  943.       int i;
  944.       int j;
  945.       char* a;
  946.       char C[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  947.       int L;
  948.       // pseudo-CRC sur fil et adr pour initialiser gΘnΘrateur alΘatoire..
  949.       unsigned int s=0;
  950.       L=strlen(C);
  951.       for(i=0;i<(int) strlen(fil_complete);i++) {
  952.         s+=(unsigned int) fil_complete[i];
  953.       }
  954.       for(i=0;i<(int) strlen(adr_complete);i++) {
  955.         s+=(unsigned int) adr_complete[i];
  956.       }
  957.       srand(s);
  958.       
  959.       j=strlen(save);
  960.       for(i=0;i<8;i++) {
  961.         char c=C[(rand()%L)];
  962.         save[i+j]=c;
  963.       }
  964.       save[i+j]='\0';
  965.       // ajouter extension
  966.       a=fil+strlen(fil)-1;
  967.       while(( a > fil) && (*a != '/') && (*a != '.')) a--;
  968.       if (*a=='.') {
  969.         strcatbuff(save,a);    // ajouter
  970.       }
  971.              } 
  972.       break;
  973.     default: {   // noms sans les noms des rΘpertoires
  974.       // ne garder que le nom, pas la structure
  975.       /*
  976.       char* a=fil+strlen(fil)-1;
  977.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  978.       if ((*a=='/') || (*a=='\\')) a++;
  979.       strcatbuff(save,a);
  980.       */
  981.  
  982.       /* add name */
  983.       ADD_STANDARD_NAME(0);
  984.             }
  985.       break;
  986.     }
  987.  
  988. #if HTS_CASSE==0
  989.     hts_lowcase(save);
  990. #endif  
  991.  
  992.     if (save[strlen(save)-1]=='/') 
  993.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  994.   }
  995.  
  996.  
  997.   // vΘrifier qu'on ne doit pas forcer l'extension
  998.   // par exemple, asp sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  999.   /*if (ext_chg) {
  1000.     char* a=save+strlen(save)-1;
  1001.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  1002.     if (*a=='.') *a='\0';  // couper
  1003.     // recopier extension
  1004.     strcatbuff(save,".");
  1005.     strcatbuff(save,ext);    // copier ext
  1006.   }*/
  1007.   // de mΩme en cas de manque d'extension on en place une de maniΦre forcΘe..
  1008.   // cela Θvite les /chez/toto et les /chez/toto/index.html incompatibles
  1009.   if (opt->savename_type != -1) {
  1010.     char* a=save+strlen(save)-1;
  1011.     while(( a > save) && (*a!='.') && (*a!='/')) a--;
  1012.     if (*a!='.') {   // agh pas de point
  1013.       //strcatbuff(save,".none");                 // a Θviter
  1014.       strcatbuff(save,".html");                   // prΘfΘrable!
  1015.       if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  1016.         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Default HTML type set for %s%s"LF,adr_complete,fil_complete);
  1017.         test_flush;
  1018.       }
  1019.     }
  1020.   }
  1021.  
  1022.   // effacer pass au besoin pour les autentifications
  1023.   // (plus la peine : masquΘ au dΘbut)
  1024. /*
  1025.   {
  1026.     char* a=jump_identification(save);
  1027.     if (a!=save) {
  1028.       char tempo[HTS_URLMAXSIZE*2];
  1029.       char *b;
  1030.       tempo[0]='\0';
  1031.       strcpybuff(tempo,"[");
  1032.       b=strchr(save,':');
  1033.       if (!b) b=strchr(save,'@');
  1034.       if (b)
  1035.         strncatbuff(tempo,save,(int) b-(int) a);
  1036.       strcatbuff(tempo,"]");
  1037.       strcatbuff(tempo,a);
  1038.       strcpybuff(save,a);
  1039.     }
  1040.   }
  1041. */
  1042.  
  1043.   // Θviter les / au dΘbut (cause: N100)
  1044.   if (save[0]=='/') {
  1045.     char tempo[HTS_URLMAXSIZE*2];
  1046.     strcpybuff(tempo,save+1);
  1047.     strcpybuff(save,tempo);
  1048.   }
  1049.  
  1050.   // changer les ~,:,",*,? en _ pour sauver sur disque
  1051.   hts_replace(save,'~','_');  // interdit sous unix (~foo)
  1052.   //
  1053.   hts_replace(save,'\\','_');
  1054.   hts_replace(save,':','_');  // interdit sous windows
  1055.   hts_replace(save,'*','_');  // interdit sous windows
  1056.   hts_replace(save,'?','_');  // doit pas arriver!!
  1057.   hts_replace(save,'\"','_');  // interdit sous windows
  1058.   hts_replace(save,'<','_');  // interdit sous windows
  1059.   hts_replace(save,'>','_');  // interdit sous windows
  1060.   hts_replace(save,'|','_');  // interdit sous windows
  1061.   //
  1062.   hts_replace(save,'@','_');
  1063.   if (opt->savename_83 == 2) { // CDROM
  1064.     // maybe other ones?
  1065.     hts_replace(save,'-','_');
  1066.     hts_replace(save,'=','_');
  1067.     hts_replace(save,'+','_');
  1068.   }
  1069.   //
  1070.   { // Θliminer les // (comme ftp://)
  1071.     char* a;
  1072.     while( (a=strstr(save,"//")) ) *a='_';
  1073.     // Eliminer chars spΘciaux
  1074.     a=save -1 ;
  1075.     while(*(++a))
  1076.       if ( ((unsigned char)(*a) <= 31)
  1077.           || ((unsigned char)(*a) == 127) )
  1078.         *a='_';
  1079.   }
  1080.  
  1081.    
  1082. #if HTS_OVERRIDE_DOS_FOLDERS
  1083.   /* Replace /foo/nul/bar by /foo/nul-/bar */
  1084.   {
  1085.     int i=0;
  1086.     while(hts_tbdev[i][0]) {
  1087.       char* a=save;
  1088.       while((a=strstrcase(a,(char*)hts_tbdev[i]))) {
  1089.         switch ( (int) a[strlen(hts_tbdev[i])] ) {
  1090.         case '\0':
  1091.         case '/':
  1092.         case '.': 
  1093.         {
  1094.           char tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0';
  1095.           strncatbuff(tempo,save,(int) (a - save) + strlen(hts_tbdev[i]));
  1096.           strcatbuff(tempo,"_");
  1097.           strcatbuff(tempo,a+strlen(hts_tbdev[i]));
  1098.           strcpybuff(save,tempo);
  1099.                    }
  1100.           break;
  1101.         }
  1102.         a+=strlen(hts_tbdev[i]);
  1103.       }
  1104.       i++;
  1105.     }
  1106.   }
  1107. #endif
  1108.  
  1109.   // conversion 8-3 .. y compris pour les rΘpertoires
  1110.   if (opt->savename_83) {
  1111.     char n83[HTS_URLMAXSIZE*2];
  1112.     long_to_83(opt->savename_83,n83,save);
  1113.     strcpybuff(save,n83);
  1114.   }
  1115.  
  1116.  
  1117.   /* ensure that there is no ../ (potential vulnerability) */
  1118.   fil_simplifie(save);
  1119.  
  1120. #if HTS_ANALYSTE
  1121.   {
  1122.     hts_htmlcheck_savename(adr_complete,fil_complete,referer_adr,referer_fil,save);
  1123.     if ( (opt->debug>0) && (opt->log!=NULL) ) {
  1124.       fspc(opt->log,"info"); fprintf(opt->log,"engine: save-name: local name: %s%s -> %s"LF,adr,fil,save);
  1125.       test_flush;
  1126.     }
  1127.   }
  1128. #endif
  1129.  
  1130.   // chemin primaire Θventuel A METTRE AVANT
  1131.   if (strnotempty(opt->path_html)) {
  1132.     char tempo[HTS_URLMAXSIZE*2];
  1133.     strcpybuff(tempo,opt->path_html);
  1134.     strcatbuff(tempo,save);
  1135.     strcpybuff(save,tempo);
  1136.   }
  1137.  
  1138.  
  1139.   // vΘrifier que le nom n'est pas dΘja pris...
  1140.   if (liens!=NULL) { 
  1141.     int nom_ok;
  1142.     do {
  1143.       int i;
  1144.       int len;
  1145.       len=strlen(save);    // taille
  1146.       //
  1147.       nom_ok=1;  // α priori bon
  1148.       // on part de la fin pour optimiser, plus les opti de taille pour aller encore plus vite..
  1149. #if DEBUG_SAVENAME
  1150. printf("\nStart search\n");
  1151. #endif
  1152.  
  1153. #if HTS_HASH
  1154.       i=hash_read(hash,save,"",0);      // lecture type 0 (sav)
  1155.       if (i>=0)
  1156. #else
  1157.       for(i=lien_tot-1;i>=0;i--) {
  1158. #if DEBUG_SAVENAME
  1159. printf("%cParse: %d",13,i);
  1160. #endif
  1161.         
  1162.         if (liens[i]->sav_len==len) {    // mΩme taille de chaεne          
  1163. #if HTS_CASSE
  1164.           if (strcmp(liens[i]->sav,save)==0)    // existe dΘja
  1165. #else
  1166.           if (strfield2(liens[i]->sav,save))    // un tel nom existe dΘja
  1167. #endif
  1168. #endif
  1169.           {
  1170. #if HTS_CASSE
  1171.             if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  1172. #else
  1173.             if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  1174. #endif
  1175.             {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  1176.               //printf("Ok, %s\n",save);
  1177.               //i=lien_tot;    // sortir
  1178.               i=0;
  1179. #if DEBUG_SAVENAME
  1180. printf("\nOK ALREADY DEFINED\n",13,i);
  1181. #endif
  1182.             } else {  // utilisΘ par un AUTRE, changer de nom
  1183.               char tempo[HTS_URLMAXSIZE*2];
  1184.               char* a=save+strlen(save)-1;
  1185.               char* b;
  1186.               int n=2;       
  1187.               tempo[0]='\0';
  1188.  
  1189. #if DEBUG_SAVENAME
  1190. printf("\nWRONG CASE UNMATCH : \n%s\n%s, REDEFINE\n",liens[i]->fil,fil_complete);
  1191. #endif
  1192.               nom_ok=0;
  1193.               i=0;
  1194.               
  1195.               while(( a > save) && (*a!='.') && (*a!='\\') && (*a!='/')) a--;
  1196.               if (*a=='.')
  1197.                 strncatbuff(tempo,save,(int) (a - save));
  1198.               else
  1199.                 strcatbuff(tempo,save);
  1200.               
  1201.               // tester la prΘsence d'un -xx (ex: index-2.html -> index-3.html)
  1202.               b=tempo+strlen(tempo)-1;
  1203.               while (isdigit((unsigned char)*b)) b--;
  1204.               if (*b=='-') {
  1205.                 sscanf(b+1,"%d",&n);
  1206.                 *b='\0';    // couper
  1207.                 n++;  // plus un
  1208.               }
  1209.               
  1210.               // en plus il faut gΘrer le 8-3 .. pas facile le client
  1211.               if (opt->savename_83) {
  1212.                 int max;
  1213.                 char* a=tempo+strlen(tempo)-1;
  1214.                 while(( a > tempo) && (*a!='/')) a--;
  1215.                 if (*a=='/') a++;
  1216.                 max=max_char-1-nombre_digit(n);
  1217.                 if ((int) strlen(a)>max)
  1218.                   *(a+max)='\0';  // couper sinon il n'y aura pas la place!
  1219.               }
  1220.               
  1221.               // ajouter -xx (ex: index.html -> index-2.html)
  1222.               sprintf(tempo+strlen(tempo),"-%d",n);
  1223.               
  1224.               // ajouter extension
  1225.               if (*a=='.')
  1226.                 strcatbuff(tempo,a);
  1227.               
  1228.               strcpybuff(save,tempo);
  1229.               
  1230.               //printf("switched: %s\n",save);
  1231.               
  1232.             }  // if
  1233. #if HTS_HASH
  1234.           }
  1235. #else
  1236.           }  // if
  1237.         }  // if sav_len
  1238.       }  // for
  1239. #endif
  1240. #if DEBUG_SAVENAME
  1241. printf("\nEnd search, %s\n",fil_complete);
  1242. #endif
  1243.     } while(!nom_ok);
  1244.     
  1245.   }
  1246.   
  1247.   //printf("'%s' %s %s\n",save,adr,fil);
  1248.       
  1249.   return 0;
  1250. }
  1251.  
  1252. /* nom avec md5 urilisΘ partout */
  1253. void standard_name(char* b,char* dot_pos,char* nom_pos,char* fil_complete,int short_ver) {
  1254.   b[0]='\0';
  1255.   /* Nom */
  1256.   if (dot_pos) {
  1257.     if (!short_ver)    // Noms longs
  1258.       strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  1259.     else
  1260.       strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  1261.   } else {
  1262.     if (!short_ver)    // Noms longs
  1263.       strcatbuff(b,nom_pos);
  1264.     else
  1265.       strncatbuff(b,nom_pos,8);
  1266.   }
  1267.   /* MD5 - 16 bits */
  1268.   strncatbuff(b,url_md5(fil_complete),4);
  1269.   /* Ext */
  1270.   if (dot_pos) {
  1271.     strcatbuff(b,".");
  1272.     if (!short_ver)    // Noms longs
  1273.       strcatbuff(b,dot_pos+1);
  1274.     else
  1275.       strncatbuff(b,dot_pos+1,3);
  1276.   } else {
  1277.     if (!short_ver)    // Noms longs
  1278.       strcatbuff(b,DEFAULT_EXT);    // pas de..
  1279.     else
  1280.       strcatbuff(b,DEFAULT_EXT_SHORT);    // pas de..
  1281.   }
  1282. }
  1283.  
  1284.  
  1285. /* Petit md5 */
  1286. char* url_md5(char* fil_complete) {
  1287.   char* digest;
  1288.   char* a;
  1289.   NOSTATIC_RESERVE(digest, char, 32+2);
  1290.   digest[0]='\0';
  1291.   a=strchr(fil_complete,'?');
  1292.   if (a) {
  1293.     if (strlen(a)) {
  1294.       char buff[HTS_URLMAXSIZE*2];
  1295.       a++;
  1296.       digest[0]=buff[0]='\0';
  1297.       strcatbuff(buff,a);         /* query string MD5 */
  1298.       domd5mem(buff,strlen(buff),digest,1);
  1299.     }
  1300.   }
  1301.   return digest;
  1302. }
  1303.  
  1304. // interne α url_savename: ajoute une chaεne α une autre avec \ -> /
  1305. void url_savename_addstr(char* d,char* s) {
  1306.   int i=strlen(d);
  1307.   while(*s) {
  1308.     if (*s=='\\')  // remplacer \ par des /
  1309.       d[i++]='/';
  1310.     else
  1311.       d[i++]=*s;
  1312.     s++;
  1313.   }
  1314.   d[i]='\0';
  1315. }
  1316.  
  1317. #undef test_flush
  1318.